import asyncio
from aiohttp import web
import aiohttp_cors
import logging
from config import *

# 设置日志级别
logging.basicConfig(level=logging.INFO)

MAX_CONCURRENT_PROCESSES = 5  # 最大同时运行的ffmpeg子进程数量

# 使用Semaphore限制并发进程数量
semaphore = asyncio.Semaphore(MAX_CONCURRENT_PROCESSES)

# 字典用于跟踪正在进行的转码任务
transcoding_tasks = {}


# 开始转码方法
async def perform_transcoding(ip, camera_id, rtmp_server):
    # 检查相同RTSP是否已有子进程在处理
    if camera_id in transcoding_tasks:
        return transcoding_tasks[camera_id]

    # 使用Semaphore限制并发进程数量
    async with semaphore:
        # 实际的转码操作，这里需要调用ffmpeg或其他工具
        # ffmpeg_command = [
        #     'ffmpeg',
        #     '-rtsp_transport', 'tcp',
        #     '-i', ip,
        #     '-c:v', 'libx264',
        #     '-c:a', 'aac',
        #     '-f', 'flv',
        #     f'{rtmp_server}/live/livestream{camera_id}'
        # ]

        ffmpeg_command = [
            'ffmpeg',
            '-rtsp_transport', 'tcp',
            '-i', ip,
            '-r', '10',  # 设置帧率为15帧/秒
            '-s', '640x360',  # 设置分辨率为640x360
            '-b:v', '400k',  # 设置视频比特率为500k
            '-c:v', 'libx264',
            '-c:a', 'aac',
            '-f', 'flv',
            f'{rtmp_server}/live/livestream{camera_id}'
        ]

        # 创建异步子进程
        process = await asyncio.create_subprocess_exec(*ffmpeg_command)

        # 将任务添加到字典中
        transcoding_tasks[camera_id] = process

        # 等待子进程完成
        await process.communicate()

        # 从字典中移除已完成的任务
        transcoding_tasks.pop(camera_id, None)


async def stop_transcoding(camera_id):
    # 停止转码任务
    if camera_id in transcoding_tasks:
        process = transcoding_tasks[camera_id]
        process.terminate()  # 发送终止信号
        await process.wait()  # 等待进程结束

        # 从字典中移除已停止的任务
        transcoding_tasks.pop(camera_id, None)


async def play_camera(request):
    data = await request.post()

    # 从表单数据中获取摄像头的ID和IP
    camera_id = data.get('id')
    ip = data.get('ip')

    # 这里设置你的 RTMP 服务器地址
    rtmp_server = SE_RTMP

    # 执行实际的转码操作
    task = await perform_transcoding(ip, camera_id, rtmp_server)
    print(task, '这里是tasktasktask', flush=True)
    if task == None:
        return web.json_response({'message': '当前视频流无法播放', 'code': 400})

    # 返回包含转码后的RTMP URL的JSON响应
    rtmp_url = f'http://{SE_VIDEO}/live/livestream{camera_id}.flv'
    # rtmp_url = f'http://192.168.14.93:8080/live/livestream{camera_id}.flv'
    return web.json_response({'message': '转码启动成功', 'flv_data': rtmp_url})


async def stop_camera(request):
    data = await request.post()
    camera_id = data.get('id')

    # 停止指定摄像头的转码任务
    await stop_transcoding(camera_id)

    return web.json_response({'code': 200, 'message': '转码停止成功'})


# 如果页面进行刷新或者关闭停止全部转码任务  请列出该方法
async def stop_all_camera(request):
    # 获取所有正在运行的任务的列表
    tasks = [stop_transcoding(camera_id) for camera_id in transcoding_tasks.keys()]

    # 并发停止所有任务
    await asyncio.gather(*tasks)

    # 清空字典，表示所有任务都已停止
    transcoding_tasks.clear()

    return web.json_response({'code': 200, 'message': '转码停止成功'})


# 回放转码播放
async def play_rtsp_replay(request):
    data = await request.post()

    # 从表单数据中获取回放的RTSP地址、开始时间和结束时间
    rtsp_url = data.get('rtsp_url')
    start_time = data.get('start_time')
    end_time = data.get('end_time')

    # 这里设置你的 RTMP 服务器地址
    rtmp_server = SE_RTMP

    # 执行实际的转码操作
    task = await perform_rtsp_replay(rtsp_url, rtmp_server, start_time, end_time)
    if task is None:
        return web.json_response({'message': '无法播放回放视频流', 'code': 400})

    # 返回包含转码后的RTMP URL的JSON响应
    rtmp_url = f'http://192.168.14.77:8081/replay/replay_stream.flv'
    # rtmp_url = f'http://192.168.14.93:8080/replay/replay_stream.flv'
    return web.json_response({'message': '回放启动成功', 'flv_data': rtmp_url})


# ffmpeg 组装
async def perform_rtsp_replay(rtsp_url, rtmp_server, start_time, end_time):
    # 使用Semaphore限制并发进程数量
    async with semaphore:
        # 实际的转码操作，这里需要调用ffmpeg或其他工具
        ffmpeg_command = [
            'ffmpeg',
            '-rtsp_transport', 'tcp',
            '-i', rtsp_url,
            '-threads', '2',  # 添加 -threads 2 参数
            '-c:v', 'libx264',
            '-c:a', 'aac',
            '-f', 'flv',
            '-ss', start_time,  # 添加开始时间参数
            '-to', end_time,  # 添加结束时间参数
            f'{rtmp_server}/replay/replay_stream'
        ]

        # 创建异步子进程
        process = await asyncio.create_subprocess_exec(*ffmpeg_command)

        # 等待子进程完成
        await process.communicate()


app = web.Application()

# CORS配置
cors = aiohttp_cors.setup(app, defaults={
    "*": aiohttp_cors.ResourceOptions(
        allow_credentials=True,
        expose_headers="*",
        allow_headers="*",
    )
})

app.router.add_route('POST', '/play_camera', play_camera)  # 开始转码任务路由
app.router.add_route('POST', '/stop_camera', stop_camera)  # 停止转码任务路由
app.router.add_route('POST', '/stop_all_camera', stop_all_camera)  # 停止全部转码任务路由
app.router.add_route('POST', '/play_rtsp_replay', stop_all_camera)  # 回放转码路由

# 添加 CORS 中间件
for route in list(app.router.routes()):
    cors.add(route)

if __name__ == '__main__':
    web.run_app(app, host='0.0.0.0', port=7000, access_log=logging.getLogger())
